package com.demo.config.apache.temporary;

import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.PDFTextStripperByArea;
import org.apache.pdfbox.text.TextPosition;
import technology.tabula.ObjectExtractor;
import technology.tabula.Page;
import technology.tabula.RectangularTextContainer;
import technology.tabula.Table;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class PDFReader {

	static String fileName = "D:\\file\\pdf\\testPdf.pdf";

	public static void main(String[] args) throws Exception {
		// 提取图片
		// extractImages(fileName);
		// 提取文字
		extractText(fileName);

		// readFile();
		// readTextImage();
		// 指定区域提取文本
		// readRectangle();

		/** 打印纲要、每一层级标题、字体样式 **/
		// getPDFOutline();
		/** 打印一级目录 **/
		// getPDFCatalog();
		/** 获取PDF文档元数据 **/
		// getPDFInformation();
		// 分页获取内容
		// readPage();

		// readTextAndTable(fileName);

	}

	private static void readTextAndTable(String path) throws IOException {
		FileOutputStream fileOutputStream;
		FileOutputStream fileOutputStream1;
		fileOutputStream = new FileOutputStream("text.txt");
		fileOutputStream1 = new FileOutputStream("table.txt");

		PDDocument pd = Loader.loadPDF(new File(path));
		ObjectExtractor oe = new ObjectExtractor(pd);
		SpreadsheetExtractionAlgorithm sea = new SpreadsheetExtractionAlgorithm(); // Tabula
																					// algo.
		int pageSize = pd.getNumberOfPages();
		// 一页一页读取
		for (int i = 0; i < pageSize; i++) {
			System.out.println("第" + (i + 1) + "页");
			Page page = oe.extract(i + 1);
			// 抽取出所有的表格内容
			List<Table> table = sea.extract(page);
			List<double[]> loc = new ArrayList<>();
			for (Table table1 : table) {
				loc.add(new double[] { table1.y, table1.y + table1.height });
				for (List<RectangularTextContainer> row : table1.getRows()) {
					fileOutputStream1
							.write((row.stream().map(RectangularTextContainer::getText).map(o -> o.replace("\r", ""))
									.collect(Collectors.joining(" | ")) + "\n").getBytes("utf-8"));
				}
				fileOutputStream1.write("\n".getBytes("utf-8"));
			}
			// 抽取出所有的文本内容
			MyPDFTextStripper stripper = new MyPDFTextStripper();
			// 设置按顺序输出
			stripper.setSortByPosition(true);
			stripper.setStartPage(i + 1);
			stripper.setEndPage(i + 1);
			stripper.setParagraphStart("\t");
			stripper.setParagraphEnd(" ");
			stripper.getText(pd);
			double lastY = 0;
			List<List<TextPosition>> charactersByArticle = stripper.myGetCharactersByArticle();
			StringBuilder pagraph = new StringBuilder();
			outer: for (int m = 0; m < charactersByArticle.get(0).size(); m++) {
				TextPosition word = charactersByArticle.get(0).get(m);
				float endY = word.getY();
				// 如果文本的y在表格的上下边框的内部，则不输出继续遍历文本
				for (double[] l : loc) {
					if (l[0] < endY && l[1] > endY) {
						continue outer;
					}
				}
				if (!word.getUnicode().equals(" ")) {
					pagraph.append(word.getUnicode());
				}
				else {
					if (lastY == endY) {
						pagraph.append(word.getUnicode());
					}
					else {
						if (!pagraph.toString().equals(" ")) {
							pagraph.append("\n");
							fileOutputStream.write(pagraph.toString().getBytes("utf-8"));
						}
						pagraph = new StringBuilder();
						pagraph.append(word.getUnicode());
						lastY = endY;
					}
				}
			}
		}
		fileOutputStream.flush();
		fileOutputStream.close();
		fileOutputStream1.flush();
		fileOutputStream1.close();
	}

	/**
	 * 获取格式化后的时间信息
	 * @param calendar 时间信息
	 * @return
	 */
	public static String dateFormat(Calendar calendar) {
		if (null == calendar)
			return null;
		String date = null;
		String pattern = "yyyy-MM-dd HH:mm:ss";
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		date = format.format(calendar.getTime());
		return date == null ? "" : date;
	}

	/** 打印纲要 **/
	public static void getPDFOutline() {
		try {
			// 打开pdf文件流
			File fdf = new File(fileName);
			// 加载 pdf 文档,获取PDDocument文档对象
			PDDocument document = Loader.loadPDF(fdf);
			// 获取PDDocumentCatalog文档目录对象
			PDDocumentCatalog catalog = document.getDocumentCatalog();
			// ============================================================================

			// ============================================================================
			// 打印字体样式
			PDPageTree pages = document.getPages();
			Iterator<PDPage> iter = pages.iterator();
			while (iter.hasNext()) {
				PDPage page = iter.next();
				PDResources resources = page.getResources();
				// 遍历资源并设置字体样式
				for (COSName fontName : resources.getFontNames()) {
					PDFont font = resources.getFont(fontName);
					if (font instanceof PDTrueTypeFont) {
						PDTrueTypeFont trueTypeFont = (PDTrueTypeFont) font;
						System.out.println("字体名称： " + trueTypeFont.getName());
						System.out.println("字体样式： " + trueTypeFont.getFontDescriptor().getFontName());
					}
					else if (font instanceof PDType1Font) {
						PDType1Font type1Font = (PDType1Font) font;
						System.out.println("字体名称： " + type1Font.getName());
						// System.out.println("字体样式： " +
						// type1Font.getFontDescriptor().getFontName());
						System.out.println("字体是否加粗：" + type1Font.getFontDescriptor().getFontWeight());
					}
					else if (font instanceof PDType0Font) {
						// 宋体
						// PDType0Font type0Font = (PDType0Font) font;
						// System.out.println("字体名称： " + type0Font.getName());
						//// System.out.println("字体样式： " +
						// type0Font.getFontDescriptor().getFontName());
						// System.out.println("字体是否加粗：" +
						// type0Font.getFontDescriptor().getFontWeight());
						// PDFontDescriptor fontDescriptor =
						// type0Font.getFontDescriptor();
					}
					else {
						// 字体名称
						String name = font.getName();
						// ============================================================================
						// ============================================================================

						System.out.println(name);
						// System.out.println(name);
					}
				}
			}
			// ============================================================================

			// ============================================================================
			// 获取PDDocumentOutline文档纲要对象
			PDDocumentOutline outline = catalog.getDocumentOutline();
			// 获取第一个纲要条目（标题1）
			PDOutlineItem item = outline.getFirstChild();
			if (outline != null) {
				// 遍历每一个标题1
				while (item != null) {
					// 打印标题1的文本
					System.out.println("Item:" + item.getTitle());
					// 获取标题1下的第一个子标题（标题2）
					PDOutlineItem child = item.getFirstChild();
					// 遍历每一个标题2
					while (child != null) {
						// 打印标题2的文本
						System.out.println("    Child:" + child.getTitle());
						// 指向下一个标题2
						child = child.getNextSibling();
					}
					// 指向下一个标题1
					item = item.getNextSibling();
				}
			}
			// 关闭输入流
			document.close();
		}
		catch (FileNotFoundException ex) {
			Logger.getLogger(PDFReader.class.getName()).log(Level.SEVERE, null, ex);
		}
		catch (IOException ex) {
			Logger.getLogger(PDFReader.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	/** 打印一级目录 **/
	public static void getPDFCatalog() {
		try {
			// 打开pdf文件流
			File fdf = new File(fileName);
			// 加载 pdf 文档,获取PDDocument文档对象
			PDDocument document = Loader.loadPDF(fdf);
			// 获取PDDocumentCatalog文档目录对象
			PDDocumentCatalog catalog = document.getDocumentCatalog();
			// 获取PDDocumentOutline文档纲要对象
			PDDocumentOutline outline = catalog.getDocumentOutline();
			// 获取第一个纲要条目（标题1）
			if (outline != null) {
				PDOutlineItem item = outline.getFirstChild();
				// 遍历每一个标题1
				while (item != null) {
					// 打印标题1的文本
					System.out.println("Item:" + item.getTitle());
					// 指向下一个标题1
					item = item.getNextSibling();
				}
			}
			// 关闭输入流
			document.close();
		}
		catch (FileNotFoundException ex) {
			Logger.getLogger(PDFReader.class.getName()).log(Level.SEVERE, null, ex);
		}
		catch (IOException ex) {
			Logger.getLogger(PDFReader.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	/** 获取PDF文档元数据 **/
	public static void getPDFInformation() {
		try {
			// 打开pdf文件流
			File fdf = new File(fileName);
			// 加载 pdf 文档,获取PDDocument文档对象
			PDDocument document = Loader.loadPDF(fdf);
			/** 文档属性信息 **/
			PDDocumentInformation info = document.getDocumentInformation();

			System.out.println("页数:" + document.getNumberOfPages());

			System.out.println("标题:" + info.getTitle());
			System.out.println("主题:" + info.getSubject());
			System.out.println("作者:" + info.getAuthor());
			System.out.println("关键字:" + info.getKeywords());

			System.out.println("应用程序:" + info.getCreator());
			System.out.println("pdf 制作程序:" + info.getProducer());

			System.out.println("Trapped:" + info.getTrapped());

			System.out.println("创建时间:" + dateFormat(info.getCreationDate()));
			System.out.println("修改时间:" + dateFormat(info.getModificationDate()));

			// 关闭输入流
			document.close();
		}
		catch (FileNotFoundException ex) {
			Logger.getLogger(PDFReader.class.getName()).log(Level.SEVERE, null, ex);
		}
		catch (IOException ex) {
			Logger.getLogger(PDFReader.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	/**
	 * 提取文本
	 * @return
	 */
	public static void extractText(String path) {
		try {
			File fdf = new File(path);
			// 通过文件名加载文档
			PDDocument pdd = Loader.loadPDF(fdf);
			// 获取文档的页数
			int pageNumber = pdd.getNumberOfPages();
			// 剥离器（读取pdf文件）
			PDFTextStripper stripper = new PDFTextStripper();
			// 排序
			stripper.setSortByPosition(true);
			// 设置要读取的起始页码
			stripper.setStartPage(1);
			// 设置要读取的结束页码
			stripper.setEndPage(pageNumber);

			// 全部内容
			String text = stripper.getText(pdd);
			// System.out.println(text);
			// =================================================
			// 生成的txt的文件路径
			// String docPath =path.substring(0,path.lastIndexOf("."))+".txt";
			// File doc = new File(docPath);
			// if(!doc.exists()){
			// doc.createNewFile();
			// }
			// 文件输出流
			// FileOutputStream fos = new FileOutputStream(doc);
			// Writer writer = new OutputStreamWriter(fos, "utf-8");
			// stripper.writeText(pdd, writer);
			// writer.close();
			// fos.close();
			// =================================================

			System.out.println("提取文本完成");
			pdd.close();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 一次获取整个文件的内容
	 * @throws Exception
	 */
	public static void readFile() throws Exception {
		File file = new File(fileName);
		PDDocument doc = Loader.loadPDF(file);
		PDFTextStripper textStripper = new PDFTextStripper();
		String s = textStripper.getText(doc);
		System.out.println("总页数：" + doc.getNumberOfPages());
		System.out.println("输出内容：");
		System.out.println(s);
		doc.close();
	}

	/**
	 * 分页获取文字的内容
	 * @throws Exception
	 */
	public static void readPage() throws Exception {
		File file = new File(fileName);
		PDDocument doc = Loader.loadPDF(file);
		PDFTextStripper textStripper = new PDFTextStripper();
		for (int i = 1; i <= doc.getNumberOfPages(); i++) {
			textStripper.setStartPage(i);
			textStripper.setEndPage(i);
			// 一次输出多个页时，按顺序输出
			textStripper.setSortByPosition(true);
			String s = textStripper.getText(doc);
			System.out.println("当前页：" + i);
			System.out.println("输出内容：");
			System.out.println(s);
		}
		// ===========================================================

		// do something with the paragraph

		// ===========================================================

		doc.close();
	}

	/**
	 * 读取文本内容和图片
	 * @throws Exception
	 */
	public static void readTextImage() throws Exception {
		File file = new File(fileName);
		PDDocument doc = Loader.loadPDF(file);
		PDFTextStripper textStripper = new PDFTextStripper();
		for (int i = 1; i <= doc.getNumberOfPages(); i++) {
			textStripper.setStartPage(i);
			textStripper.setEndPage(i);
			String s = textStripper.getText(doc);
			System.out.println("第 " + i + " 页 :" + s);
			// 读取图片
			PDPage page = doc.getPage(i - 1);
			PDResources resources = page.getResources();
			// 获取页中的对象
			Iterable<COSName> xobjects = resources.getXObjectNames();
			if (xobjects != null) {
				Iterator<COSName> imageIter = xobjects.iterator();
				while (imageIter.hasNext()) {
					COSName cosName = imageIter.next();
					boolean isImageXObject = resources.isImageXObject(cosName);
					if (isImageXObject) {
						// 获取每页资源的图片
						PDImageXObject ixt = (PDImageXObject) resources.getXObject(cosName);
						File outputfile = new File("第 " + (i) + " 页" + cosName.getName() + ".jpg");
						ImageIO.write(ixt.getImage(), "jpg", outputfile);
					}
				}
			}
		}
		doc.close();
	}

	/**
	 * 区域解析 指定区域提取文本
	 * @throws Exception
	 */
	public static void readRectangle() throws Exception {
		String filePath = fileName;
		File file = new File(filePath);
		PDDocument doc = Loader.loadPDF(file);
		// 这个四边形所在区域在 y轴向下为正，x轴向右为正。
		int x = 35;
		int y = 500;
		int width = 500;
		int height = 500;
		PDFTextStripperByArea stripper = new PDFTextStripperByArea();
		stripper.setSortByPosition(true);
		// 划定区域
		Rectangle2D rect = new Rectangle(x, y, width, height);
		stripper.addRegion("area", rect);
		PDPage page = doc.getPage(1);
		stripper.extractRegions(page);
		// 获取区域的text
		String data = stripper.getTextForRegion("area");
		data = data.trim();
		System.out.println(data);
		doc.close();
	}

	/**
	 * 提取图片
	 * @return
	 */
	public static boolean extractImages(String path) {
		boolean result = true;
		try {
			File fdf = new File(path);
			// 通过文件名加载文档
			PDDocument document = Loader.loadPDF(fdf);
			PDPageTree pages = document.getPages();
			Iterator<PDPage> iter = pages.iterator();
			// 生成的txt的文件路径
			String imagePath = path.substring(0, path.lastIndexOf("."));
			while (iter.hasNext()) {
				PDPage page = iter.next();
				PDResources resources = page.getResources();
				resources.getXObjectNames().forEach(e -> {
					try {
						if (resources.isImageXObject(e)) {
							PDImageXObject imageXObject = (PDImageXObject) resources.getXObject(e);
							BufferedImage bufferedImage = imageXObject.getImage();
							System.out.println(bufferedImage);
							ImageIO.write(bufferedImage, "jpg", new File(imagePath + "_" + e + ".jpg"));
						}

					}
					catch (IOException ioException) {
						ioException.printStackTrace();
					}
				});
				System.out.println("----------------------------------------------");
			}
			System.out.println("提取图片完成");
			// document.save(fdf);
			document.close();
		}
		catch (IOException ex) {
			ex.printStackTrace();
			return false;
		}
		return result;
	}

}
